#include <gtk/gtk.h>
#include <stdio.h>
#include <time.h>
#include <glib/gprintf.h>
#include <string.h>
#include <stdlib.h>
#include <gdk/gdkcursor.h>
#include "visualizer.h"

#define LEN_OF_CHROM 10000
#define num_of_char_at_bottom 100
#define IMG_H 20
#define IMG_W 1000
#define stack_size 10000
#define zoom_factor 2.f
#define num_of_color 3

typedef int ULL;

int max_freq;
int zoomed_to_bottom;
int chrom_data[LEN_OF_CHROM];
char dna_strand[LEN_OF_CHROM];
unsigned char color_map[num_of_color][3];
unsigned char pix_data[IMG_W*3];
int nX,nY;
ULL bg, ed;
GdkPixbuf *pb;
GtkWidget *window,*vbox,*hbox, *zoom, *event_box, *out_hbox, *right_vbox;
GtkWidget *legend_box[num_of_color];
GtkLabel *bottom_label;
GtkImage *im, *legend_color[num_of_color];

typedef struct{
	int top;
	ULL bg_stack[stack_size];
	ULL ed_stack[stack_size];
} pos_stack;

pos_stack st;

void calc_color(char* pixel, double data){
	int i;
	int m=(int)(data*num_of_color)/max_freq;
//	printf("%4.2f %d %d %d \n",x,n,max_freq,m);
	if (m>=num_of_color)
		m=num_of_color;	
	for (i=0; i<3; i++)
		pixel[i]=color_map[m][i];
}

void zoom_out(){
	if (st.top==-1)
		return;
	bg=st.bg_stack[st.top];
	ed=st.ed_stack[st.top];
	st.top--;
	update_image();
}

void quit(){
	gtk_main_quit();
}


void update_pix_data(){
    ULL i=bg, k;
	ULL chunk_len=(ed-bg)/IMG_W;
	//printf("%d %d %d \n", bg, ed, chunk_len);
	int j;
	for (j=0; j<IMG_W*3; j+=3){
		double avg=0.0;
		for (k=0; k<chunk_len && i+k<LEN_OF_CHROM; k++) 
			avg=avg+(double)chrom_data[k+i];		
		i=i+k;
		avg=avg/((double)chunk_len);

		calc_color(pix_data+j,avg);
/*
		pix_data[j]=255*avg;
		pix_data[j+1]=255*(1-avg);
		pix_data[j+2]=0;*/
	}

	
}

void zoom_to_bottom(int bg, int ed){
	char text[num_of_char_at_bottom];
	int i;
	for (i=0; i<num_of_char_at_bottom; i++)
		text[i]=chrom_data[bg+i];
	gtk_label_set_text(bottom_label, text);

	gtk_container_remove (GTK_CONTAINER(event_box), (GtkWidget*)im);
	gtk_container_add(GTK_CONTAINER(event_box),(GtkWidget*)bottom_label);
//	gtk_widget_reparent (bottom_label,event_box);
}

void zoom_in(gdouble x){
	double norm_loc=x/IMG_W;
	ULL len=ed-bg;	
	ULL center=bg+(ULL)(len*norm_loc);
	ULL new_len=(ULL) (len/zoom_factor);

	if (new_len<=IMG_W){
		int dummy_bg=center-(new_len)/2 >=0 ? center-(new_len)/2 : 0;
		int dummy_ed=center+(new_len)/2 <LEN_OF_CHROM ? center+(new_len)/2 : LEN_OF_CHROM;
		zoom_to_bottom(dummy_bg,dummy_ed);
		return;   
	}

	
	st.top++;
	st.bg_stack[st.top]=bg;	
	st.ed_stack[st.top]=ed;
	bg=center-(new_len)/2 >=0 ? center-(new_len)/2 : 0;
	ed=center+(new_len)/2 <LEN_OF_CHROM ? center+(new_len)/2 : LEN_OF_CHROM;
	update_image();
}

static gint button_press_event(GtkWidget * widget,
          GdkEventButton * event, gpointer data)
{
        if (event->button == 1)      
        { 
			zoom_in(event->x);
	      	//printf("%4.2f   %4.2f   \n",event->x,event->y);				
        }
		else if (event->button == 3)
		{
			zoom_out();
		}
        return TRUE;
}

void fill_pixbuf(int color, GdkPixbuf *temp){
  int ht,wt;
  int i=0,j=0;
  int rowstride=0;  
  int bpp=3;
  guchar *pixel;
 // printf("%d \n", color);

  bpp=3;	   

  int n_channels = gdk_pixbuf_get_n_channels (temp);

  g_assert (gdk_pixbuf_get_colorspace (temp) == GDK_COLORSPACE_RGB);
  g_assert (gdk_pixbuf_get_bits_per_sample (temp) == 8);
  g_assert (!gdk_pixbuf_get_has_alpha (temp));
  g_assert (n_channels==3);

  ht=gdk_pixbuf_get_height(temp);
  //printf("%d \n",ht);
  wt=gdk_pixbuf_get_width(temp);
//  printf("%d \n",wt);
  pixel=gdk_pixbuf_get_pixels(temp);
  printf("%d %d %d %d\n",gdk_pixbuf_get_rowstride(temp),gdk_pixbuf_get_bits_per_sample(temp),
		  gdk_pixbuf_get_width(temp), gdk_pixbuf_get_height(temp)) ;
  rowstride=wt*bpp;
//  temp->rowstride=rowstride;
  for(i=0;i<ht;i++)		
    for(j=0;j<rowstride;j+=bpp)   
      {	
    	pixel[i*rowstride + j+0]=color_map[color][0];
    	pixel[i*rowstride + j+1]=color_map[color][1];
    	pixel[i*rowstride + j+2]=color_map[color][2];
//        printf("%d %d %d \n",color_map[color][0],color_map[color][1],color_map[color][2]);
  //      printf("%d %d %d \n",pixel[i*rowstride + j+0],pixel[i*rowstride + j+1],pixel[i*rowstride + j+2]);
      }
  return;
}

void update_image()
{
  int ht,wt;
  int i=0,j=0;
  int rowstride=0;  
  int bpp=0;
  guchar *pixel;
  update_pix_data();
  bpp=3;	   
  ht=IMG_H;   
  wt=IMG_W;	  
  pixel=gdk_pixbuf_get_pixels(pb);
  rowstride=wt*bpp;
 // printf("%d asda\n ",rowstride);
  for(i=0;i<ht;i++)		
    for(j=0;j<rowstride;j+=bpp)   
      {	
    	pixel[i*rowstride + j + 0]=pix_data[j];
    	pixel[i*rowstride + j + 1]=pix_data[j+1];
    	pixel[i*rowstride + j + 2]=pix_data[j+2];
      //  printf("%d %d\n",pixel[i*rowstride + j + 0],pix_data[j]);
//        printf("%d %d %d \n",pixel[i*rowstride + j+0],pixel[i*rowstride + j+1],pixel[i*rowstride + j+2]);

      }
  gtk_image_set_from_pixbuf(im,pb);
  return;
}

void set_up_window()
{

  //event box and image
  pb=gdk_pixbuf_new(GDK_COLORSPACE_RGB,0,8,IMG_W,IMG_H);
  im=gtk_image_new_from_pixbuf(pb);
  printf("aaa %d \n",gdk_pixbuf_get_rowstride(pb));
  update_image();
  event_box = gtk_event_box_new ();
  gtk_container_add (GTK_CONTAINER(event_box), (GtkWidget*)im);

  gtk_widget_set_events(event_box,  
                   GDK_BUTTON_PRESS_MASK );

  gtk_signal_connect(GTK_OBJECT(event_box), "button_press_event",
               (GtkSignalFunc) button_press_event, event_box);       



  //window
  window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
  gtk_window_set_default_size(GTK_WINDOW(window),1200,400);
  gtk_signal_connect(GTK_OBJECT(window),"destroy",GTK_SIGNAL_FUNC(quit),NULL);

  //button
  zoom=gtk_button_new_with_mnemonic("_Zoom out");
  g_signal_connect(GTK_OBJECT(zoom),"clicked",G_CALLBACK(zoom_out),NULL);



  //packing box
  vbox=gtk_vbox_new(FALSE,FALSE);

  out_hbox=gtk_hbox_new(FALSE,FALSE);
  right_vbox=gtk_vbox_new(FALSE,FALSE);

  //legend_box
  int i,j,k;
  for ( i=0; i<num_of_color; i++){
    GdkPixbuf *temp_buf=gdk_pixbuf_new(GDK_COLORSPACE_RGB,FALSE,8,40,40);
    printf("%d \n",gdk_pixbuf_get_rowstride(temp_buf));
    g_object_ref(temp_buf);
	fill_pixbuf(i,temp_buf);
    legend_box[i]=gtk_hbox_new(FALSE,FALSE);
    gtk_box_pack_start_defaults(GTK_BOX(legend_box[i]), gtk_image_new_from_pixbuf(temp_buf));
	gtk_box_pack_start_defaults(GTK_BOX(right_vbox), legend_box[i]);
    g_object_unref(temp_buf);
  }

  gtk_box_pack_start_defaults(GTK_BOX(vbox),event_box);
//  gtk_box_pack_start_defaults(GTK_BOX(vbox),gtk_hseparator_new());
  gtk_box_pack_start_defaults(GTK_BOX(vbox),zoom);
  //gtk_box_pack_start_defaults(GTK_BOX(vbox),gtk_hseparator_new());
  gtk_box_pack_start_defaults(GTK_BOX(out_hbox),vbox);
  gtk_box_pack_start_defaults(GTK_BOX(out_hbox),right_vbox);


  gtk_container_add(GTK_CONTAINER(window),out_hbox);


  gtk_widget_show_all(window);
  gtk_main();

}

void test(){
	srand(time(NULL));
	int i;
	max_freq=0;
	for (i=0; i<LEN_OF_CHROM; i++){
		chrom_data[i]=rand() % 12413;
		max_freq=max_freq<chrom_data[i] ? chrom_data[i] : max_freq;
		dna_strand[i]='A';
	}
}

void init_color_map(){
	//color 0
	color_map[0][0]=255;
	color_map[0][1]=120;
	color_map[0][2]=0;

	//color 1
	color_map[1][0]=120;
	color_map[1][1]=120;
	color_map[1][2]=120;

    //color 2

	color_map[2][0]=0;
	color_map[2][1]=120;
	color_map[2][2]=225;
}

void init_param(){
	bg=0; 
	ed=LEN_OF_CHROM-1;
	st.top=-1;
	init_color_map();
	zoomed_to_bottom=0;
	test();
}


int main(int argc,char *argv[])
{
	gtk_init(&argc,&argv);
	init_param();
	set_up_window();
	return 0;
}
